package com.by.auth;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import java.util.*;

/*
 * Token封装
 * */
@Component
public class TokenTemplate {
    //密钥
    @Value("${token.secret}")
    String secret;


    //Token默认有效期
    @Value("${token.validTime}")
    long validTime;

    //默认过期事件
    private final
    long DEFAULT_Time = 30 * 60 * 1000;//默认三十分钟

    /*
     * 生成Token
     * */
    public String generateToken(Map payload) {
        String token = JWT.create()
                .withHeader(getHeader())
                .withPayload(payload)
                .withExpiresAt(getDate())//给token设置有效期
                .sign(Algorithm.HMAC256(getSecret()));
        return token;
    }

    /*
     * 验证token
     *
     * */
    public ValidResult validateToken(String token) {
        //判断传过来的Token是否为空
        if (null == token || "".equals(token)) {
            return new ValidResult(0, "Token为空", null);
        }
        //不为null就开始验证
        DecodedJWT decodedJWT;
        try {
            decodedJWT = JWT.require(Algorithm.HMAC256(secret))
                    .build()
                    .verify(token);
        } catch (TokenExpiredException e) {
            //Token过期异常
            return new ValidResult(0, "Token已过期!", null);
        } catch (Exception e) {
            return new ValidResult(1, "Token无效", null);
        }
        //验证通过 给出提示并返回用户信息
        Map map = decodedJWT.getClaims();
        return new ValidResult(2, "验证通过", convert(map));
    }


    /*
    * 刷新Token
    *
    * */

    public String refreshToken(String token) {
//        验证Token
        ValidResult result = validateToken(token);
//        判断Token状态
        if (result.getCode()==1){//无效
            return null;
        }else if(result.getCode()==2){
//            过期
            DecodedJWT decodedJWT=JWT.decode(token);
//            获取用户信息
            Map<String,Claim> map=decodedJWT.getClaims();
//            生成新Token
            return generateToken(convert(map));
        }
        //Token正常时刷新
        Map map=result.getUser();
        //生成新的Token
        return generateToken(map);
    }





    /*
    * 解析用户信息方便查看
    * */
    Map<String,String> convert(Map<String, Claim> payload) {
        Map<String,String> map = new HashMap<>();
        payload.forEach((k,v)->{
            map.put(k,v.asString());
        });
        return map;
    }
    /*
     * 有效期设置
     * */
    Date getDate() {
        long time = System.currentTimeMillis() + getValidTime();//当前秒加上输入的秒数秒即过期日期
        Date date = new Date(time);
        return date;
    }


    public String getSecret() {
        if (null == secret) {
//            如果为null则随机生成一个三十六位的字符串
            secret = UUID.randomUUID().toString();
        }
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public long getValidTime() {
//        如果用户没有输入有效时长则返回默认时长
        if (0 == validTime) {
            return DEFAULT_Time;
        } else {
            //由于默认为毫秒所以*1000转为秒
            return validTime * 1000;
        }

    }

    public void setValidTime(long validTime) {
        this.validTime = validTime;
    }

    /*
     * 头部
     * */
    Map getHeader() {
        Map map = new HashMap();
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        return map;
    }

}
